package com.california.pay.task;

import com.alibaba.fastjson.JSON;
import com.california.pay.common.utils.DateUtils;
import com.california.pay.config.ServerConfig;
import com.california.pay.facade.MchOrderNotifyFacade;
import com.california.pay.model.MchOrderPayNotifyMchReq;
import com.california.pay.model.MchOrderPayNotifyMchRsp;
import com.california.pay.persist.domain.PayOrder;
import com.california.pay.persist.mapper.PayOrderMapper;
import com.california.pay.result.CommonResult;
import com.california.pay.service.BaseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 通知商户任务
 */
@Slf4j
public class MchPayOrderNotifyTask {
    @Autowired
    private PayOrderMapper payOrderMapper;
    @Autowired
    private MchOrderNotifyFacade notifyFacade;
    private ExecutorService executorService = Executors.newCachedThreadPool();


    public void retryNotify() {
        BaseService.initTraceId(this.getClass().getSimpleName() + "#personMchOrderPay");
        log.info("开始调度[MchPayOrderNotifyTask#retryNotify]任务，重新发起通知。");
        Date now = new Date();
        Integer minNotifyDates = ServerConfig.propertiesLoader.getInteger("min.notify.dates");
        Long minNotifyDate = Long.parseLong(DateUtils.yyyyMMdd(now)) - minNotifyDates;
        Integer totalNotifyCount = ServerConfig.propertiesLoader.getInteger("total.notify.count");

        List<PayOrder> payOrders = payOrderMapper.getNotifyMchFailList(minNotifyDate, totalNotifyCount);
        for (PayOrder payOrder : payOrders) {
            executorService.submit(() -> notifyMch(payOrder.getOrderId()));
        }
        log.info("调度[MchPayOrderNotifyTask#retryNotify]任务完成");
    }

    public void notifyMch(String innerOrderId) {
        PayOrder payOrder = payOrderMapper.selectByPrimaryKey(innerOrderId);
        CommonResult<MchOrderPayNotifyMchRsp> result = null;
        try {
            result = notifyFacade.payOrderNotifyMch(getNotifyMchReq(payOrder));
            addCountsByNotify(payOrder);
        } catch (Exception e) {
            log.error("[MchPayOrderNotifyTask#retry]支付调用 notify url 失败, innerOrderId=" + innerOrderId, e);
        }
        log.info("[MchPayOrderNotifyTask#retry]支付调用 notify url调用成功, innerOrderId={}, result={}", innerOrderId, JSON.toJSONString(result));
    }

    @Transactional(rollbackFor = {Exception.class})
    public void addCountsByNotify(PayOrder payOrder){
        PayOrder updatePayOrder = new PayOrder();
        updatePayOrder.setOrderId(payOrder.getOrderId());
        updatePayOrder.setUpdateTime(new Date());
        updatePayOrder.setMchNotifyCount(payOrder.getMchNotifyCount() + 1);
        payOrderMapper.updateByPrimaryKeySelective(updatePayOrder);
    }

    private MchOrderPayNotifyMchReq getNotifyMchReq(PayOrder payOrder) {
        MchOrderPayNotifyMchReq req = new MchOrderPayNotifyMchReq();
        req.setOutOrderNo(payOrder.getMchOrderNo());
        req.setInnerOrderNo(payOrder.getInnerOrderNo());
        req.setTotalAmount(payOrder.getTotalAmount());
        req.setTxnAmount(payOrder.getTxnAmount());
        req.setChannelUserId(payOrder.getChannelUserId());
        req.setNotifyUrl(payOrder.getMchNotifyUrl());
        req.setReturnUrl(payOrder.getMchReturnUrl());
        req.setRemark("通知商户消息重试.");
        req.setSystemTime(LocalDateTime.now());
        req.setInnerMchNo(payOrder.getInnerMchNo());
        return req;
    }
}
